home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / drcpas10.zip / KEYBOARD.PAS < prev    next >
Pascal/Delphi Source File  |  1992-11-17  |  6KB  |  255 lines

  1. {$A+,B-,D-,F-,I+,L-,N-,O-,R-,S+,V-}
  2. unit keyboard;
  3.  
  4. (* by David R. Conrad, for Turbo Pascal 5.5
  5.  
  6.    This code is not copyrighted, you may use it freely.
  7.    There are no guarantees, either expressed or implied,
  8.    as to either merchantability or fitness for a particular
  9.    purpose.  The author's liability is limited to the amount
  10.    you paid for it.
  11.  
  12.    David R. Conrad, 17 Nov 92
  13.    David_Conrad@mts.cc.wayne.edu
  14.    dave@michigan.com
  15. *)
  16.  
  17. interface
  18.  
  19. const
  20.   (* for testing shift key status *)
  21.   RIGHTSHIFT = $01;
  22.   LEFTSHIFT  = $02;
  23.   CTRLKEY    = $04;
  24.   ALTKEY     = $08;
  25.   SCROLLLOCK = $10;
  26.   NUMLOCK    = $20;
  27.   CAPSLOCK   = $40;
  28.   INSTOGGLE  = $80;
  29.   (* these constants are only for enhanced keyboards *)
  30.   LEFTCTRL   = $0100;
  31.   LEFTALT    = $0200;
  32.   RIGHTCTRL  = $0400;
  33.   RIGHTALT   = $0800;
  34.   SCROLLDOWN = $1000;
  35.   NUMDOWN    = $2000;
  36.   CAPSDOWN   = $4000;
  37.   SYSRQDOWN  = $8000;
  38.   (* for setting the delay rate *)
  39.   delay250   = 0;
  40.   delay500   = 1;
  41.   delay750   = 2;
  42.   delay1000  = 3;
  43.   (* for setting the repeat rate *)
  44.   fastkey    = $00;
  45.   defaultkey = $0C;
  46.   slowkey    = $1F;
  47.  
  48. var
  49.   scancode, asciival : char;
  50. {$IFDEF SCREENSAVE}
  51.   lastkeypress, timeout : longint;
  52.   screensaver : procedure;
  53. {$ENDIF}
  54.  
  55. (* all routines are documented in the implementation section *)
  56.  
  57. function readkey : char;
  58. function keypressed : boolean;
  59. function shiftkeys : word;
  60. function enhanced : boolean;
  61. procedure typematic (kbddelay, repeatrate : byte);
  62. function pushkey (ch : char) : boolean;
  63. procedure clearkeys;
  64. procedure waitkey;
  65.  
  66. implementation
  67.  
  68. uses dos, dostools
  69. {$IFDEF SCREENSAVE}
  70.                   , timer
  71. {$ENDIF}
  72.                          ;
  73.  
  74. const
  75.   kbdint = $16;
  76.  
  77. var
  78.   second : char;
  79.   readfunc, pressfunc, shiftfunc : byte;
  80.  
  81. function readkey : char;
  82. (* get key press, wait for one if necessary *)
  83. (* returns #0 then scan code for extended keys, just like CRT.readkey *)
  84. (* note: also puts ascii value and scan code in asciival and scancode *)
  85. (* note: if SCREENSAVE is defined, calls keypressed repeatedly to allow
  86.    screen saver to get control; see keypressed *)
  87. var
  88.   r : registers;
  89. begin
  90.   if second <> #0 then
  91.     begin
  92.       readkey := second;
  93.       second := #0;
  94.     end
  95.   else
  96.     begin
  97. {$IFDEF SCREENSAVE}
  98.       repeat until keypressed;
  99. {$ENDIF}
  100.       initregisters (r);
  101.       r.ah := readfunc;
  102.       intr (kbdint, r);
  103.       if (r.al = $E0) and (r.ah <> 0) then r.al := 0;
  104.       readkey := char(r.al);
  105.       asciival := char(r.al);
  106.       scancode := char(r.ah);
  107.       if r.al = 0 then second := char(r.ah);
  108.     end;
  109. {$IFDEF SCREENSAVE}
  110.   lastkeypress := ClockTix;
  111. {$ENDIF}
  112. end;
  113.  
  114. function keypressed : boolean;
  115. (* tell whether any keystrokes are waiting; has a key been pressed? *)
  116. (* note: if a key has been pressed, puts ascii value and scan code of
  117.    key in asciival and scancode, allowing:
  118.    if keypressed and (asciival = #27) then ....
  119.    This does not remove the keystroke from the typeahead buffer.  *)
  120. (* note: if SCREENSAVE is defined and more that timeout timer ticks
  121.    have occured since the lastkeypress, the screen saver is invoked. *)
  122. var
  123.   r : registers;
  124.   p : procedure;
  125. begin
  126.   if second <> #0 then
  127.     keypressed := true
  128.   else
  129.     begin
  130. {$IFDEF SCREENSAVE}
  131.       if (@screensaver <> nil) and
  132.          (difftix(lastkeypress, ClockTix) > timeout) then
  133.         begin
  134.           p := screensaver;
  135.           @screensaver := nil;
  136.           p;
  137.           screensaver := p;
  138.           lastkeypress := ClockTix;
  139.         end;
  140. {$ENDIF}
  141.       initregisters (r);
  142.       r.ah := pressfunc;
  143.       intr (kbdint, r);
  144.       if (r.al = $E0) and (r.ah <> 0) then r.al := 0;
  145.       if (r.flags AND FZero) = FZero then
  146.         keypressed := false
  147.       else
  148.         begin
  149.           keypressed := true;
  150.           asciival := char(r.al);
  151.           scancode := char(r.ah);
  152.         end;
  153.     end;
  154. end;
  155.  
  156. function shiftkeys : word;
  157. (* get shift key state: upper byte only valid with enhanced keyboard *)
  158. var
  159.   r : registers;
  160. begin
  161.   initregisters (r);
  162.   r.ah := shiftfunc;
  163.   intr (kbdint, r);
  164.   shiftkeys := r.ax;
  165. end;
  166.  
  167. function enhanced : boolean;
  168. (* tell whether an enhanced keyboard BIOS is present *)
  169. var
  170.   r : registers;
  171.   a : byte;
  172. begin
  173.   initregisters (r);
  174.   r.ah := $02;
  175.   intr (kbdint, r);
  176.   a := NOT r.al;
  177.   r.ah := $12;
  178.   r.al := a;
  179.   intr (kbdint, r);
  180.   enhanced := a <> r.al;
  181. end;
  182.  
  183. procedure typematic (kbddelay, repeatrate : byte);
  184. (* set the typematic delay and repeat rate on an enhanced keyboard *)
  185. var
  186.   r : registers;
  187. begin
  188.   initregisters (r);
  189.   r.ah := $03;
  190.   r.al := $05;
  191.   if kbddelay > delay1000 then kbddelay := delay250;
  192.   if repeatrate > slowkey then repeatrate := fastkey;
  193.   r.bh := kbddelay;
  194.   r.bl := repeatrate;
  195.   intr (kbdint, r);
  196. end;
  197.  
  198. function pushkey (ch : char) : boolean;
  199. (* push a keystroke back into the typeahead buffer *)
  200. (* note: the contents of the scancode variable are used for the scan code
  201.    of the key; if the scan code matters, place it in that variable prior
  202.    to calling this routine *)
  203. (* note: will return false if the typeahead buffer is full or if no
  204.    enhanced BIOS present *)
  205. var
  206.   r : registers;
  207. begin
  208.   initregisters (r);
  209.   r.ah := $05;
  210.   r.al := $01;
  211.   r.cl := byte(ch);
  212.   r.ch := byte(scancode);
  213.   intr (kbdint, r);
  214.   pushkey := r.al = 0;
  215. end;
  216.  
  217. procedure clearkeys;
  218. (* clear the typeahead buffer *)
  219. begin
  220.   while keypressed do if readkey = #0 then if readkey = #0 then;
  221. end;
  222.  
  223. procedure waitkey;
  224. (* wait for a keypress *)
  225. begin
  226.   if readkey = #0 then if readkey = #0 then;
  227. end;
  228.  
  229. (* note: because of the auto-detection of the enhanced ROM BIOS and use
  230.    of appropriate function numbers, these routine will work on original
  231.    PC's and XT's and also allow full access to all features of enhanced
  232.    keyboards, e.g. F11 & F12.
  233. *)
  234.  
  235. begin
  236.   second := #0;
  237.   if enhanced then
  238.     begin
  239.       readfunc  := $10;
  240.       pressfunc := $11;
  241.       shiftfunc := $12;
  242.     end
  243.   else
  244.     begin
  245.       readfunc  := $00;
  246.       pressfunc := $01;
  247.       shiftfunc := $02;
  248.     end;
  249. {$IFDEF SCREENSAVE}
  250.   @screensaver := nil;
  251.   timeout := 5460;
  252.   lastkeypress := ClockTix;
  253. {$ENDIF}
  254. end.
  255.